package cn.myframe.controller;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.RandomStringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableId;

import cn.myframe.utils.annotation.DefaultValue;
import cn.myframe.utils.annotation.IgnoreCopy;
import cn.myframe.service.BaseService;
import cn.myframe.shiro.ShiroUtils;
import cn.myframe.utils.DateUtils;
import cn.myframe.utils.ReflectUtils;
import cn.myframe.utils.core.PageUtils;
import cn.myframe.utils.core.Query;
import cn.myframe.utils.core.R;

public interface BaseController<T,S extends BaseService<T>> {

    S getService();

    default  R defaultList(@RequestParam Map<String, Object> params){
        Query query = new Query(params);
        PageUtils pageUtil = getService().queryPage(query);
        return R.ok().put("page", pageUtil);
    };

   // @RequestMapping("/info/{id}")
    default R defaultInfo(@PathVariable("id") Long id,String entityName){
       T t =  getService().queryObject(id);
       return R.ok().put(entityName, t);
    }


    default R defaultSave(@RequestBody T t){    	
    	initEntity(t);
    	getService().insert(t);
    	return R.ok();
    }
    
    /**
     * 删除方法
     * @param ids
     * @return
     */
    default R defaultDelete(Long[] ids){
    	List<Long> idList = Arrays.asList(ids);
    	getService().deleteBatchIds(idList);
        return R.ok();
     }
    
    default R defaultAudit(Long[] ids,Integer status){
    	getService().updateStatus(ids, status);
        return R.ok();
     }
    
    default R defaultUpdate(T t){
    	Long key = (Long)ReflectUtils.getKeyValue(t);
    	T oT =  getService().queryObject(key);
    	getService().updateById(t);  
        return R.ok().put("oldObject", oT);
     }
    
    default R defaultCopy(Long id){
    	T t = getService().queryObject(id);
    	initCopyEntity(t);
    	try {
    	//	Object bean = SpringContextUtils.getBean(t.getClass());
    		Method controllerMethod = this.getClass().getDeclaredMethod("save", t.getClass());
    		R result = (R)controllerMethod.invoke(this, t);
    		return result;
		} catch (Exception e) {
			e.printStackTrace();
		} 
    //	getService().insert(t);
    	return R.ok();
    }
    
    default String defaultCheckExist(String id,String value,String columnName){
        boolean result = true;
        int count = getService().checkExist(id, value,columnName);
        if(count > 0 ){
            result = false;
        }
        return "{\"valid\":" + result + "}";
    }
    
    
    public default  void initEntity(T t){
		try {
			Class<? extends Object> clz = t.getClass();
    	 //   clz.getDeclaredMethods();
    	    Date date = new Date();
    	    String timeStr = DateUtils.format(date, DateUtils.DATE_TIME_PATTERN);
    	    Field[] fields = clz.getDeclaredFields();
    	    for(Field f : fields){
    	    	f.setAccessible(true);
	    		String typeName = f.getType().getName();
    			if(f.getName().equals("status") || "auditStatus".equals(f.getName())){        					
					if(typeName.equals("java.lang.Integer")){
						f.set(t, 0);
    				}else if(typeName.equals("java.lang.Long")){
    					f.set(t, 0L);
    				}
    			}else if(f.getName().equals("createBy")||f.getName().equals("creatorId")||f.getName().equals("creator_id")
    					||f.getName().equals("creater")||f.getName().equals("updateBy")||f.getName().equals("create_user_id")){
    				if(typeName.equals("java.lang.Integer")||typeName.equals("java.lang.Long")){
    					f.set(t, ShiroUtils.getUserEntity().getUserId());
    				}else if(typeName.equals("java.lang.String")){
    					f.set(t, ShiroUtils.getUserEntity().getUsername());
    				}
    				
    			}else if(f.getName().equals("createTime")||f.getName().equals("updateTime")){
    				if(typeName.equals("java.util.Date")){
    					f.set(t, date);
    				}else if(typeName.equals("java.lang.String")){
    					f.set(t, timeStr);
    				}else if(typeName.equals("java.lang.Long")){
    					f.set(t, date.getTime());
    				}
    			}
    	    }
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
    
    /**
     * 生成copy实体
     * @param t
     */
    public default void initCopyEntity(T t){
    	try {
    		Class<? extends Object> clz = t.getClass();
        	Field[] fields = clz.getDeclaredFields();
    	    for(Field f : fields){
    	    	boolean ignoreCopyBoolean = f.isAnnotationPresent(IgnoreCopy.class);
    	    	if(ignoreCopyBoolean){
    	    		IgnoreCopy annotation = f.getAnnotation(IgnoreCopy.class);  
    	    		f.setAccessible(true);
    	    		String value = randomValue( t,f,annotation.value(),3);
    	    		f.set(t,value);
    	    	}
    	    	boolean defaultValueBoolean = f.isAnnotationPresent(DefaultValue.class);
    	    	if(defaultValueBoolean){
    	    		String typeName = f.getType().getName();
    	    		f.setAccessible(true);
    	    		DefaultValue defaultValue = f.getAnnotation(DefaultValue.class);
    	    		String value = defaultValue.value();
    	    		if(typeName.equals("java.lang.Integer")){
						f.set(t, Integer.parseInt(value));
    				}else if(typeName.equals("java.lang.String")){
    					f.set(t, value);
    				}
    	    	}
    	    	boolean tableIdBoolean = f.isAnnotationPresent(TableId.class);
    	    	if(tableIdBoolean){
    	    		f.setAccessible(true);
    	    		f.set(t, null);
    	    	}
    	    }
		} catch (Exception e) {
		}
    	initEntity(t);
    }

    /**
     * 生成固定位数的随机字符串
     * @param t
     * @param f
     * @param length
     * @param iteration  迭代数次,防死循环
     * @return 
     */
    public default String randomValue(T t,Field f,int length,int iteration){
    	String randomString =  RandomStringUtils.randomAlphanumeric(length);
		boolean isAnnotation = f.isAnnotationPresent(TableField.class);
		//数据库字段
		String columnName = f.getName();
    	try {
    		if(isAnnotation){
    			TableField tableField = f.getAnnotation(TableField.class); 
    			columnName = tableField.value();
    			String value = String.valueOf(f.get(t));
    			int len = length - value.length() - 3;
    			if(len >= 0 && iteration > 0){
    				randomString = value + "["+RandomStringUtils.randomAlphanumeric(len)+"]";
    			}
    		}
    		int count = getService().checkExist(null, randomString,columnName);
    		if(count > 0){
    			return randomValue( t, f, length,iteration-1);
    		}
		} catch (Exception e) {
			
		}
		return randomString;
    }
    
    



}
